package cn.com.cetccst.mdm.engine;

import android.Manifest;
import android.app.Activity;
import android.app.csdk.CSDKManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

public class LenovoMdmEngine extends BaseMDMEngine {

    private static final String TAG = "LenvovMdmEngine";
    private CSDKManager csdkManager;

    public LenovoMdmEngine(Context context) {
        super(context);
        csdkManager = new CSDKManager(context);
    }

    @Override
    public void config(ComponentName adminComponent, String fileProviderAuthority, Callback logger) {
        super.config(adminComponent, fileProviderAuthority, logger);
        csdkManager.enableDeviceAdmin(adminComponent.flattenToString(), true);
    }

    @Override
    public boolean isActiveDeviceAdmin() {
        return devicePolicyManager.isAdminActive(adminComponent);
    }

    @Override
    public boolean setActiveDeviceAdmin(Activity activity) {
        return true;
    }

    @Override
    public void controlBluetooth(boolean disabled) {
        csdkManager.enableBluetoothV3(!disabled);
        csdkManager.enableBluetoothTetheringV3(!disabled);
        csdkManager.disallowBluetoothV3(disabled);
        csdkManager.disallowBluetoothShareV3(disabled);
        csdkManager.disallowBluetoothTetheringV3(disabled);
    }

    @Override
    public boolean isBluetoothControlled() {
        return csdkManager.getDisallowBluetoothV3Status();
    }

    @Override
    public boolean setBluetoothWhiteList(List<String> whitList) {
        try {
            List<String> bluetoothDevices = getBluetoothWhiteList();
            for (String device : getBluetoothWhiteList()) {
                Log.d(TAG, "getBluetoothWhiteList : " + device);
            }
            ArrayList<String> needRemoveDevices = getNeedRemoveDevices(bluetoothDevices, whitList);
            removeBluetoothDevicesFromWhiteList(needRemoveDevices);
            csdkManager.addBtWhiteList(whitList);

            for (String device : getBluetoothWhiteList()) {
                Log.d(TAG, "add bluetooth devices whiteList success : " + device);
            }
            return true;
        } catch (Exception e) {
            Log.d(TAG, "add bluetooth devices whiteList find Exception", e);
        }
        return false;
    }

    ArrayList<String> getNeedRemoveDevices(List<String> devicesDB, List<String> bluetoothDevices) {
        ArrayList<String> needRemoveDevices = new ArrayList<>();
        for (String device : devicesDB) {
            if (!bluetoothDevices.contains(device)) {
                Log.d(TAG, "getNeedRemoveDevices1:" + device);
                needRemoveDevices.add(device);
            }
        }
        return needRemoveDevices;
    }

    public void removeBluetoothDevicesFromWhiteList(ArrayList<String> devices) {

        removeBondedDevices(devices);
        csdkManager.removeBtWhiteList(getBluetoothWhiteList());
        Log.d(TAG, "removeBluetoothDevicesFromWhiteList :" + getBluetoothWhiteList().size());
        for (String device : devices) {
            if (getBluetoothWhiteList().contains(device)) {
                Log.d(TAG, "remove bluetooth devices whiteList failed");
            }
        }
    }

    private void removeBondedDevices(ArrayList<String> devices) {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
        if (bluetoothAdapter != null) {
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "No BLUETOOTH_CONNECT permission.");
            }
            Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
            Log.d(TAG, "need removeBond : " + pairedDevices.size());
            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {
                    String address = device.getAddress(); // MAC地址
                    Log.d(TAG, "need removeBond address: " + address);
                    if (devices.contains(address.toLowerCase()) || devices.contains(address.toUpperCase())) {
                        Log.d(TAG, "need removeBond : " + device.getAddress());
                        bluetoothDevices.add(device);
                    }
                }
            } else {
                Log.d(TAG, "No devices are paired.");
            }
        }

        try {
            for (BluetoothDevice device : bluetoothDevices) {
                Method removeBondMethod = BluetoothDevice.class.getMethod("removeBond");
                removeBondMethod.invoke(device);
                Log.d(TAG, "invoke removeBond : " + device.getAddress());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<String> getBluetoothWhiteList() {
        return new ArrayList<>(csdkManager.getBtWhiteList());
    }

    @Override
    public void controlCamera(boolean disabled) {
        csdkManager.disableCamera(disabled);
    }

    @Override
    public boolean isCameraControlled() {
        return csdkManager.getCameraStatus();
    }

    @Override
    public void controlWifi(boolean disabled) {
        if (disabled) {
            csdkManager.enableWifiV3(false);
        }
        csdkManager.disallowWifiV3(disabled);
    }
    @Override
    public boolean isWifiControlled() {
        return csdkManager.getDisallowWifiV3Status();
    }

    @Override
    public boolean setWifiWhiteList(List<String> whiteList) {
        if (whiteList == null) {
            csdkManager.enableWifiWhiteList(false);
        } else {
            csdkManager.enableWifiWhiteList(true);
            csdkManager.removeWifiWhiteList(csdkManager.getWifiWhiteList());
            csdkManager.addWifiWhiteList(whiteList);
        }
        return true;
    }

    @Override
    public List<String> getWifiWhitList() {
        return csdkManager.getWifiWhiteList();
    }

    @Override
    public void controlExternalStorage(boolean disabled) {
        csdkManager.disableStorage(disabled);
        csdkManager.enableMassStorage(!disabled);
    }

    @Override
    public boolean isExternalStorageControlled() {
        return !csdkManager.getEnableMassStorageStatus();
    }

    @Override
    public void controlScreenShot(boolean disabled) {
        csdkManager.enableCaptureScreenV3(!disabled);
    }

    @Override
    public boolean isScreenShotControlled() {
        return !csdkManager.getEnableCaptureScreenV3Status();
    }

    @Override
    public void controlMobileHotSpot(boolean disabled) {
        csdkManager.enableWifiHotspotV3(!disabled);
        csdkManager.disallowWifiHotspotV3(disabled);
    }

    @Override
    public boolean isMobileHotSpotControlled() {
        return csdkManager.getWifiHotSpotStatus();
    }

    @Override
    public void controlMobileData(boolean disabled) {
        csdkManager.enableDataV3(!disabled);
        csdkManager.disallowDataV3(disabled);
    }

    @Override
    public boolean isMobileDataControlled() {
        return csdkManager.isDisallowData();
    }

    @Override
    public void controlVolumeDown(boolean disabled) {
        csdkManager.requestKeyControl_V3(25, disabled);
        csdkManager.requestKeyControl_V3(24, disabled);
    }

    @Override
    public boolean isVolumeDownControlled() {
        return csdkManager.getVolumeKeyStatus() == 0;
    }

    @Override
    public void controlAutoTime(boolean disabled) {
        csdkManager.disallowSetSysTimeV3(disabled);
        csdkManager.disallowSetSysDateV3(disabled);
        csdkManager.disallowSetSysTimeZoneV3(disabled);
    }

    @Override
    public boolean isAutoTimeControlled() {
        return csdkManager.disableTimeZoneStatus();
    }

    @Override
    public void controlUsbData(boolean disabled) {
        if (disabled) {
            csdkManager.setCurrentUsbMode(0);
        }
        csdkManager.disallowUsbModeV3(disabled);
    }

    @Override
    public boolean isUsbDataControlled() {
        return csdkManager.getUsbModeV3Status();
    }

    @Override
    public void controlUsbDebug(boolean disabled) {
        if (disabled) {
            //csdkManager.enableUsbDebugging(!disabled);
        }
        csdkManager.disallowUsbDebuggingV3(disabled);
        csdkManager.disallowDevModeV3(disabled);
    }

    @Override
    public boolean isUsbDebugControlled() {
        return !csdkManager.getUsbDebuggingStatus();
    }

    @Override
    public void controlRestoreFactory(boolean disabled) {
        csdkManager.disallowFactoryResetV3(disabled);
    }

    @Override
    public boolean isRestoreFactoryControlled() {
        return csdkManager.getDisallowFactoryResetV3Status();
    }

    @Override
    public void controlSystemUpgrade(boolean disabled) {
        csdkManager.disallowAutoOta(disabled);
    }

    @Override
    public boolean isSystemUpgradeControlled() {
        return csdkManager.getDisallowAutoOtaStatus();
    }

    @Override
    public void controlGPS(boolean disabled) {
        if (disabled) {
            csdkManager.enableLocationV3(false);
        }
        csdkManager.disallowLocationV3(disabled);
    }

    @Override
    public boolean isGPSControlled() {
        return !csdkManager.getLocationStatus();
    }


    @Override
    public boolean setDisallowRunningApps(List<String> packageNames, boolean block) {
        List<String> pendingList = new ArrayList<>();
        if (packageNames != null) {
            List<String> blockedList = csdkManager.getUnRunAppPackageList();
            if (blockedList == null || blockedList.isEmpty()) {
                pendingList.addAll(packageNames);
            } else {
                Log.d(TAG, "blockedList size " + blockedList.size() + "/" + block);
                for (String source : packageNames) {
                    PackageInfo packageInfo = null;
                    try {
                        packageInfo = context.getPackageManager().getPackageInfo(source, PackageManager.GET_UNINSTALLED_PACKAGES);
                    } catch (PackageManager.NameNotFoundException e) {
                        //
                    }
                    if (packageInfo == null) {
                        continue;
                    }
                    if (block) {
                        if (!blockedList.contains(source)) {
                            pendingList.add(source);
                        }
                    } else {
                        if (blockedList.contains(source)) {
                            pendingList.add(source);
                        }
                    }
                }
            }

            if (block) {
                if (!pendingList.isEmpty()) {
                    csdkManager.addUnRunAppPackageList(pendingList);
                    Log.d(TAG, "set packages to be disabled via Lenovo with size " + pendingList.size());
                }
            } else {
                if (!pendingList.isEmpty()) {
                    csdkManager.removeUnRunAppPackageList(pendingList);
                    Log.d(TAG, "set packages to be enable via Lenovo with size " + pendingList.size());
                }
            }
        }
        return false;
    }

    @Override
    public List<String> getDisallowRunningApps() {
        return csdkManager.getUnRunAppPackageList();
    }

    @Override
    public boolean setUninstallblockApps(List<String> packageNames) {
        if (packageNames == null || packageNames.size() == 0) {
            csdkManager.disableUnInstallation(false);
            csdkManager.removeUninstallPackageBlackList(csdkManager.getUninstallPackageBlackList());
        } else {
            Log.d(TAG, "setUninstallblockApps: " + packageNames.get(0));
            csdkManager.disableUnInstallation(true);
            csdkManager.removeUninstallPackageBlackList(csdkManager.getUninstallPackageBlackList());
            csdkManager.addUninstallPackageBlackList(packageNames);
        }
        return true;
    }

    @Override
    public List<String> getUninstallblockApps() {
        return csdkManager.getUninstallPackageBlackList();
    }

    @Override
    public boolean setInstallblockApps(List<String> packageNames) {
        if (packageNames != null && packageNames.size() > 0) {
            csdkManager.disableInstallation(true);
            csdkManager.addInstallPackageBlackList(packageNames);
        } else {
            csdkManager.disableInstallation(false);
            csdkManager.removeInstallPackageBlackList(csdkManager.getInstallPackageBlackList());
        }
        return true;
    }

    @Override
    public List<String> getInstallblockApps() {
        return csdkManager.getInstallPackageBlackList();
    }

    @Override
    public void installPackage(String apkPath) {
        csdkManager.installPackage(apkPath, false);
    }

    @Override
    public void uninstallPackage(String packageName) {
        csdkManager.uninstallPackage(packageName, false);
    }

    @Override
    public void factoryReset() {
        csdkManager.launchFactoryReset();
    }

    @Override
    public boolean setInstallSourceApps(List<String> packageNames) {
        return false;
    }

    @Override
    public List<String> getInstallSourceApps() {
        return null;
    }

    @Override
    public boolean setNetworkWhiteListApps(List<String> packageNames) {
        return false;
    }

    @Override
    public List<String> getNetworkWhiteListApps() {
        return null;
    }

    @Override
    public boolean setKeepLiveApps(List<String> packageNames) {
        csdkManager.cleanZmcLmkWhiteList();
        csdkManager.cleanBootCompletedWhiteList();
        csdkManager.cleanNetSleepWhiteList();

        csdkManager.addZmcLmkWhiteList(packageNames);
        csdkManager.addBootCompletedWhiteList(packageNames);
        csdkManager.addNetSleepWhiteList(packageNames);

        return true;
    }

    @Override
    public List<String> getKeepLiveApps() {
        return csdkManager.getZmcLmkWhiteList();
    }

    @Override
    public boolean setSuperApps(List<String> packageNames) {
        return false;
    }

    @Override
    public List<String> getSuperApps() {
        return null;
    }

    @Override
    public boolean controlDeviceOwner(boolean enable) {
        if (enable) {
            if (!devicePolicyManager.isAdminActive(adminComponent)) {
                csdkManager.enableDeviceAdmin(adminComponent.flattenToString(), true);
            }
            if (!devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) {
                csdkManager.setDeviceOwner("com.zdk.mg.agent/com.zdk.mdm.engine.MdmDeviceAdminReceiver");
                checkAndSetResetPasswordToken(context.getApplicationContext());
            }
        } else {
            try {
                devicePolicyManager.clearDeviceOwnerApp(context.getPackageName());
            } catch (Exception e) {
            }
        }
        return true;
    }

    @Override
    public boolean isDeviceOwnerControlled() {
        return devicePolicyManager.isDeviceOwnerApp(context.getPackageName());
    }

    @Override
    public boolean setDevicePassword(String password) {
        return csdkManager.setLockPassword(password);
    }

    @Override
    public void shutdown() {
        csdkManager.shutdownDevice();
    }

    @Override
    public void reboot() {
        csdkManager.rebootDevice();
    }

    @Override
    public void powerOnAt(long time) {
        Date now = new Date();
        now.setTime(now.getTime() + 120 * 1000);
        Log.e(TAG, "power on at " + now.getHours() + " " + now.getMinutes());
        csdkManager.setBootTime(true, now.getHours(), now.getMinutes(), -1, 0);
    }

    @Override
    public String getSN() {
        return csdkManager.getDeviceInfo(2);
    }

    @Override
    public String getName() {
        return "Lenovo";
    }
}
